package com.chatplus.application.processor.channel.chat.chatglm;

import com.chatplus.application.common.logging.SouthernQuietLogger;
import com.chatplus.application.common.logging.SouthernQuietLoggerFactory;
import com.chatplus.application.domain.dto.ChatConfigDto;
import com.chatplus.application.domain.entity.basedata.ApiKeyEntity;
import com.chatplus.application.processor.AIChannelServiceProvider;
import com.chatplus.application.processor.channel.chat.IChatAiProcessorService;
import com.chatplus.application.processor.constant.AIConstants;
import com.chatplus.application.processor.constant.AiPlatformConstants;
import com.chatplus.application.processor.handler.dto.ChatRecordMessage;
import com.chatplus.application.processor.listener.ChatGLMEventSourceListener;
import com.chatplus.application.service.basedata.ApiKeyService;
import com.chatplus.application.service.basedata.ConfigService;
import com.zhipu.oapi.ClientV3;
import com.zhipu.oapi.Constants;
import com.zhipu.oapi.core.httpclient.OkHttpTransport;
import com.zhipu.oapi.service.v3.ModelApiRequest;
import com.zhipu.oapi.service.v3.ModelConstants;
import okhttp3.OkHttpClient;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.net.Proxy;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;


/**
 * 百度 文心一言 机器人处理器
 *
 * @author chj
 * @date 2023/12/27
 **/
@Service(value = AIChannelServiceProvider.SERVICE_NAME_PRE + "ChatGLM")
public class ChatGLMAiProcessor extends IChatAiProcessorService {
    private static final SouthernQuietLogger LOGGER = SouthernQuietLoggerFactory.getLogger(ChatGLMAiProcessor.class);
    private final ConfigService configService;
    private final ApiKeyService apiKeyService;

    public ChatGLMAiProcessor(ConfigService configService
            , ApiKeyService apiKeyService) {
        this.configService = configService;
        this.apiKeyService = apiKeyService;
    }

    @Override
    public void process(List<ChatRecordMessage> messageContext) {
        ChatConfigDto chatConfigDto = configService.getChatConfig();
        ChatConfigDto.ChatGmlBean chatGmlBean = chatConfigDto.getChatGml();
        if (chatGmlBean == null) {
            replyErrorMessage("加载系统配置失败，连接已关闭！！！");
            return;
        }
        List<ApiKeyEntity> apiKeys = apiKeyService.getApiKeys(getChannel(), "chat");
        // // 更新 API KEY 的最后使用时间
        if (CollectionUtils.isEmpty(apiKeys)) {
            replyErrorMessage("抱歉😔😔😔，系统已经没有可用的 API KEY，请联系管理员！");
            replyErrorMessage(AIConstants.ERROR_MSG);
            replyErrorMessage(AIConstants.ERR_IMG);
            return;
        }
        // TODO 这个后续可以考虑弄成多个配置，做轮询
        ApiKeyEntity apiKeyEntity = apiKeys.get(0);
        String[] arrStr = apiKeyEntity.getValue().split("\\.");
        ClientV3 client = new ClientV3.Builder(arrStr[0], arrStr[1])
                .httpTransport(new OkHttpTransport(getInstance()))
                .build();
        String prompt = messageContext.stream()
                .filter(msg -> msg.getReply() == null)
                .map(ChatRecordMessage::getPrompt)
                .collect(Collectors.joining());

        ModelApiRequest modelApiRequest = new ModelApiRequest();

        String modelName = getSession().getAttributes().get("modelName").toString();
        modelApiRequest.setModelId(modelName);
        modelApiRequest.setInvokeMethod(Constants.invokeMethodSse);
        modelApiRequest.setReturnType(Constants.RETURN_TYPE_JSON);
        List<ModelApiRequest.Prompt> messages = new ArrayList<>();
        messageContext.forEach(msg -> {
            ModelApiRequest.Prompt promptMessage = new ModelApiRequest.Prompt(ModelConstants.roleUser, msg.getPrompt());
            messages.add(promptMessage);
            if (StringUtils.isNotEmpty(msg.getReply())) {
                ModelApiRequest.Prompt replyMessage = new ModelApiRequest.Prompt(ModelConstants.roleAssistant, msg.getReply());
                messages.add(replyMessage);
            }
        });
        modelApiRequest.setPrompt(messages);
        String requestId = String.format("chat-%d", System.currentTimeMillis());
        modelApiRequest.setRequestId(requestId);
        modelApiRequest.setSseListener(new ChatGLMEventSourceListener(getSession(), getChannel(), prompt));
        client.invokeModelApi(modelApiRequest);
    }

    // 请先填写自己的apiKey再调用demo查看效果
    public static OkHttpClient getInstance() {
        OkHttpClient okHttpClient = new OkHttpClient.Builder()//构建器
                .proxy(Proxy.NO_PROXY) //来屏蔽系统代理
                .retryOnConnectionFailure(true)
                .connectTimeout(300, TimeUnit.SECONDS)//连接超时
                .writeTimeout(300, TimeUnit.SECONDS)//写入超时
                .readTimeout(300, TimeUnit.SECONDS)//读取超时
                .build();
        okHttpClient.dispatcher().setMaxRequestsPerHost(200); //设置最大并发请求数，避免等待延迟
        okHttpClient.dispatcher().setMaxRequests(200);
        return okHttpClient;
    }

    @Override
    public String getChannel() {
        return AiPlatformConstants.CHAT_GLM;
    }
}